/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2011.10.11                                          *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_bdry_NeumannBoundaryCondition_h
#define FreeMAPs_include_COMMON_bdry_NeumannBoundaryCondition_h

#include "FreeMAPsConfig.h"

//LIBMESH headers

//COMMON headers
#include "COMMON/bdry/IrregularBoundaryConditionStrategy.h"
#include "COMMON/enum/DirectionType.h"
#include "COMMON/tbox/Point.h"


namespace gFreeMAPs
{
class ParaFluxBean;
}

namespace FreeMAPs
{

//forward declarations
#ifdef FREEMAPS_HAVE_SAMRAI
class AttributeOfCell;
#endif
class Function;

/**
 * the boundary condition has the form of
 *   \f[ \mathbf{K}(\mathbf{\nabla f}\cdot\mathbf{N}) = flux \f]
 * or in component format:
 *   \f[ K_{x}N_x\frac{df}{dx}+K_{y}N_y\frac{df}{dy}+K_{z}N_z\frac{df}{dz} = flux \f]
 *
 * where \f$ \mathbf{K}=(K_{x}, K_{y}, K_{z})\f$ is the coefficient of first order item.
 * \f$ \mathbf{N}=(N_x, N_y, N_z)\f$ is the out-normal direction of the boundary
 * \f$ \nabla f=grad (f)=(\frac{df}{dx}, \frac{df}{dy}, \frac{df}{dz})\f$ is the gradient of the field
 * \f$ flux \f$ is the flux on the boundary defined by user.
 */
class NeumannBoundaryCondition : public IrregularBoundaryConditionStrategy
{
public:

    NeumannBoundaryCondition (
            const std::string& parent_name,
            const std::string& bc_name,
            const PDEEquationEnsembleStrategy* equation_ensemble);

    virtual
    ~NeumannBoundaryCondition();

public:

    /**
     * @return the boundary condition type
     */
    inline BoundaryConditionType
    get_type() const;

    inline bool
    require_set_variable() const;

private:

    void
    clear();

    void
    get_info_for_derived_object_from_input (
        const InputDatabase* db);

    std::string
    get_info_from_derived_object() const;

public:
    virtual void set_para_flux(
            gFreeMAPs::ParaFluxBean* para_flux);

    virtual gFreeMAPs::ParaFluxBean*
    get_para_flux();

    virtual void set_coef_absorption(
            const std::string& coef_absorption);

    virtual const std::string&
        get_coef_absorption();

    virtual void set_direction_type(
            const DirectionType& type);

    virtual const DirectionType&
    get_direction_type();

    virtual void set_direction(
            const double& x,
            const double& y,
            const double& z);

    virtual const double
    get_direction_x();

    virtual const double
    get_direction_y();

    virtual const double
    get_direction_z();

private:

    typedef IrregularBoundaryConditionStrategy Parent;


private:
    //Function* d_para_flux;
    gFreeMAPs::ParaFluxBean* d_para_flux;

    //Function* d_coef_absorption;
    std::string d_coef_absorption;

    /*
     * Can be "ISOTROPIC" or "COLLIMATION".
     * when direction_type="ISOTROPIC", nothing else to be done.
     * when direction_type="COLLIMATION", then fb will be multiplied by a factor
     *      witch is considered by this director with the boundary's normal. Default to "ISOTROPIC".
     */
    DirectionType d_direction_type;

    /*
     * Used when direction_type=="COLLIMATION", give the component of cosine of this direction
     * with the axis x, y and z.
     */
    //Point d_direction;

    /*
     * Used when direction_type="COLLIMATION". The factor will be set to 0
     * if the direction is back to the boundary when set to FALSE. Default to TRUE.
     */
    bool d_is_back_direction_allowable;

private:

    DISALLOW_COPY_AND_ASSIGN (NeumannBoundaryCondition);
};

}

#include "COMMON/bdry/NeumannBoundaryCondition.inl"

#endif
